﻿using Microsoft.CSharp;
using System;
using System.CodeDom;
using System.CodeDom.Compiler;
using System.Collections.Generic;
using System.ComponentModel;
using System.IO;
using System.Linq;
using System.Net;
using System.Reflection;
using System.Security.Cryptography;
using System.Text;
using System.Threading.Tasks;
#if NET45 || NET40
using System.Web.Services;
using System.Web.Services.Description;
using System.Web.Services.Discovery;
using System.Web.Services.Protocols;
using System.Xml.Schema;
using System.Xml.Serialization;
using HCenter.CommonUtils.WebServiceDataProvider;

namespace HCenter.CommonUtils.WebServiceDataProvider
{
    /// <summary>  
    /// 通过 wsdl调用Webservice  
    /// </summary>  
    public class WebServiceHelper
    {
        #region 私有变量和属性定义
        /// <summary>                   
        /// web服务地址                           
        /// </summary>                              
        private string _wsdlUrl = string.Empty;
        /// <summary>                   
        /// web服务名称                           
        /// </summary>                              
        private string _wsdlClassName = string.Empty;

        /// <summary>
        /// 一个WebService数据源提供程序的连接类
        /// </summary>
        private Connection _connection = null;
        #endregion

        #region 公共属性定义
        /// <summary>
        /// 获取或设置WebService的地址
        /// </summary>
        public string URL { get { return _connection?.URL; } set { if (_connection != null) _connection.URL = value; } }

        /// <summary>
        /// 获取或设置用于登录WebService所在站点的用户名
        /// </summary>
        public string UserName { get { return _connection?.UserName; } set { if (_connection != null) _connection.UserName = value; } }

        /// <summary>
        /// 获取或设置用于登录WebService所在站点的密码
        /// </summary>
        public string Password { get { return _connection?.Password; } set { if (_connection != null) _connection.Password = value; } }

        /// <summary>
        /// 获取或设置用于登录WebService所在站点的域
        /// </summary>
        public string Domain { get { return _connection?.Domain; } set { if (_connection != null) _connection.Domain = value; } }
        #endregion

        #region 构造函数
        /// <summary>
        /// 初始化一个WebService代理类的实例
        /// </summary>
        /// <param name="wsdlUrl">WebService的地址</param>
        /// <param name="useDefaultCredentials">此站点是否使用默认身份认证</param>
        public WebServiceHelper(string wsdlUrl, bool useDefaultCredentials = false)
        {
            this._wsdlUrl = wsdlUrl;
            _connection = new Connection(wsdlUrl, useDefaultCredentials);

            var classes = _connection.GetClassList();
            if (classes == null || classes.Count() == 0)
            {
                throw new Exception(wsdlUrl + "未找到该WebService的类");
            }
            this._wsdlClassName = classes.FirstOrDefault();

        }
        #endregion

        #region Query/Execute
        /// <summary>
        /// 从远处服务器查询数据
        /// </summary>
        /// <param name="method">方法名</param>
        /// <param name="pars">入参集合</param>
        /// <returns>查询结果对象</returns>
        public object Query(string method, params object[] pars)
        {
            var methodCommand = _connection.GetMethodCommand(method, _wsdlClassName);
            if (pars?.Length > 0)
            {
                for (var i = 0; i < pars.Length; i++) methodCommand[i] = pars[i];
            }
            var ret = methodCommand.Query();
            return ret;
        }
        /// <summary>
        /// 从远处服务器查询数据
        /// </summary>
        /// <param name="method">方法名</param>
        /// <param name="pars">入参集合</param>
        /// <returns>查询结果对象</returns>
        public T Query<T>(string method, params object[] pars)
        {
            var ret = Query(method, pars);
            return Newtonsoft.Json.JsonConvert.DeserializeObject<T>(Newtonsoft.Json.JsonConvert.SerializeObject(ret));
        }
        /// <summary>
        /// 执行远处服务指定方法，无返回值
        /// </summary>
        /// <param name="method">方法名</param>
        /// <param name="pars">入参集合</param>
        public void Execute(string method, params object[] pars)
        {
            var ret = Query(method, pars);
        }
        #endregion

        #region WebService相关操作
        /// <summary>
        /// 设置WebService的类
        /// </summary>
        /// <returns>类列表</returns>
        public bool SetWsdlClassName(string wsdlClassName)
        {
            var cls = GetClassList();
            if (cls?.Contains(wsdlClassName) == true)
            {
                _wsdlClassName = wsdlClassName;
                return true;
            }
            return false;
        }
        /// <summary>
        /// 获取一个列表，该列表包含了此WebService的类
        /// </summary>
        /// <returns>类列表</returns>
        public IEnumerable<string> GetClassList()
        {
            return _connection?.GetClassList();
        }

        /// <summary>
        /// 获取一个列表，该列表包含了此WebService的类中的方法
        /// </summary>
        /// <returns>方法列表</returns>
        public IEnumerable<string> GetMethodList()
        {
            return _connection?.GetMethodList(this._wsdlClassName);
        }

        /// <summary>
        /// 获取指定方法的描述
        /// </summary>
        /// <param name="method">方法名</param>
        /// <returns>指定方法的描述</returns>
        public string GetMethodDescription(string method)
        {
            return _connection?.GetMethodDescription(this._wsdlClassName, method);
        }

        /// <summary>
        /// 获取指定方法的参数列表
        /// </summary>
        /// <param name="method">方法名</param>
        /// <returns>指定方法的描述</returns>
        public Dictionary<string, string> GetMethodParameterList(string method)
        {
            return _connection?.GetMethodParameterList(this._wsdlClassName, method);
        }

        /// <summary>
        /// 获取指定方法的返回类型
        /// </summary>
        /// <param name="method">方法名</param>
        /// <returns>指定方法的描述</returns>
        public string GetMethodReturnType(string method)
        {
            return _connection?.GetMethodReturnType(this._wsdlClassName, method);
        }

        /// <summary>
        /// 获取类似文档的方法说明
        /// </summary>
        /// <param name="method">方法名</param>
        /// <returns></returns>
        public string GetMethodDoc(string method)
        {
            return _connection?.GetMethodDoc(this._wsdlClassName, method);
        }

        /// <summary>
        /// 获取类的描述
        /// </summary>
        /// <returns>指定类的描述</returns>
        public string GetClassDescription()
        {
            return _connection?.GetClassDescription(this._wsdlClassName);
        }
        #endregion
    }
    #region WebServiceHelper
    //public static class WebServiceHelper
    //{
    //    /// <summary>
    //    /// 动态调用WebService
    //    /// </summary>
    //    /// <param name="url">WebService地址</param>
    //    /// <param name="methodname">方法名(模块名)</param>
    //    /// <param name="args">参数列表,无参数为null</param>
    //    /// <returns>object</returns>
    //    public static object InvokeWebService(string url, string methodname, object[] args)
    //    {
    //        return InvokeWebService(url, null, methodname, args);
    //    }
    //    /// <summary>
    //    /// 动态调用WebService
    //    /// </summary>
    //    /// <param name="url">WebService地址</param>
    //    /// <param name="classname">类名</param>
    //    /// <param name="methodname">方法名(模块名)</param>
    //    /// <param name="args">参数列表</param>
    //    /// <returns>object</returns>
    //    public static object InvokeWebService(string url, string classname, string methodname, object[] args)
    //    {
    //        string @namespace = "fangqm.Netbank.WebService.webservice";
    //        if (classname == null || classname == "")
    //        {
    //            classname = WebServiceHelper.GetClassName(url);
    //        }
    //        //获取服务描述语言(WSDL)
    //        WebClient wc = new WebClient();
    //        Stream stream = wc.OpenRead(url + "?WSDL");//【1】
    //        ServiceDescription sd = ServiceDescription.Read(stream);//【2】
    //        ServiceDescriptionImporter sdi = new ServiceDescriptionImporter();//【3】
    //        sdi.AddServiceDescription(sd, "", "");
    //        CodeNamespace cn = new CodeNamespace(@namespace);//【4】
    //                                                         //生成客户端代理类代码
    //        CodeCompileUnit ccu = new CodeCompileUnit();//【5】
    //        ccu.Namespaces.Add(cn);
    //        sdi.Import(cn, ccu);
    //        //CSharpCodeProvider csc = new CSharpCodeProvider();//【6】
    //        var icc = new CSharpCodeProvider();// csc.CreateCompiler();//【7】
    //                                                     //设定编译器的参数
    //        CompilerParameters cplist = new CompilerParameters();//【8】
    //        cplist.GenerateExecutable = false;
    //        cplist.GenerateInMemory = true;
    //        cplist.ReferencedAssemblies.Add("System.dll");
    //        cplist.ReferencedAssemblies.Add("System.XML.dll");
    //        cplist.ReferencedAssemblies.Add("System.Web.Services.dll");
    //        cplist.ReferencedAssemblies.Add("System.Data.dll");
    //        //编译代理类
    //        CompilerResults cr = icc.CompileAssemblyFromDom(cplist, ccu);//【9】
    //        if (true == cr.Errors.HasErrors)
    //        {
    //            System.Text.StringBuilder sb = new StringBuilder();
    //            foreach (CompilerError ce in cr.Errors)
    //            {
    //                sb.Append(ce.ToString());
    //                sb.Append(System.Environment.NewLine);
    //            }
    //            throw new Exception(sb.ToString());
    //        }

    //        //生成代理实例,并调用方法
    //        System.Reflection.Assembly assembly = cr.CompiledAssembly;
    //        Type t = assembly.GetType(@namespace + "." + classname, true, true);
    //        object bj = Activator.CreateInstance(t);//【10】
    //        System.Reflection.MethodInfo mi = t.GetMethod(methodname);//【11】
    //        return mi.Invoke(bj, args);

    //    }
    //    private static string GetClassName(string url)
    //    {
    //        //假如URL为"http://localhost/InvokeService/Service1.asmx"
    //        //最终的返回值为 Service1
    //        string[] parts = url.Split('/');
    //        string[] pps = parts[parts.Length - 1].Split('.');
    //        return pps[0];
    //    }
    //}
    #endregion
}
#endif